<template>
  <div class="custom-tree-container" v-loading="loading">
    <div class="flex_sb">
      <div class="flex">
        <el-switch
          class="switch"
          v-model="selectTreeAll"
          @change="changeTreeSelect"
        />
        菜单全选
      </div>
      <div class="flex">
        <el-switch
          class="switch"
          v-model="selectAuthAll"
          @change="changeAuthSelect"
        />
        权限全选
        <el-tooltip
          effect="dark"
          content="使用权限全选功能，默认选中全部菜单"
          placement="top"
        >
          <vab-icon
            icon="error-warning-line"
            style="color: #fbb28a; margin-left: 4px"
          />
        </el-tooltip>
      </div>
    </div>

    <el-tree
      show-checkbox
      ref="treeRef"
      node-key="name"
      check-strictly
      :data="dataSource"
      :props="treeProps"
      default-expand-all
      :expand-on-click-node="false"
      :default-checked-keys="defaultChecked"
      @check-change="checkChange"
    >
      <template #default="{ node, data }">
        <span class="custom-tree-node">
          <span>{{ retrunRouterTitle(node.label) }}</span>
          <el-radio-group v-model="node.data.authName" class="ml-4">
            <el-radio :label="`${retrunRouterName(node)}.all`" size="large">
              全部
            </el-radio>
            <el-radio
              :label="`${retrunRouterName(node)}.readonly`"
              size="large"
            >
              只读
            </el-radio>
          </el-radio-group>
        </span>
      </template>
    </el-tree>
  </div>
</template>

<script lang="ts" setup>
  import { ref } from 'vue'
  import type Node from 'element-plus/es/components/tree/src/model/node'
  import { asyncRoutes } from '~/src/router'
  import { VabRouteMeta } from '~/src/router/types'
  import { ArrayFlat, ArrayOneValue, StrSplit } from '~/src/utils/utils'
  import _ from 'lodash'

  /***
   * @var
   */
  // 本地路由【除系统设置】
  const routerList = ref<any>(
    asyncRoutes.filter((item: any) => item.name != 'Setting')
  )
  // 初始化全部路由name集合
  const initAllRouter = ref<any>(
    ArrayOneValue(ArrayFlat(routerList.value, 'children'), 'name')
  )
  // 树状结构数据
  const dataSource = ref<VabRouteMeta[]>(routerList.value)

  // 树状实例
  const treeRef = ref()
  // 加载
  const loading = ref(false)
  // 全选keys
  const defaultChecked = ref<any>([])

  //当复选框被点击的时候触发
  const checkChange = (row: any) => {
    const node = treeRef.value.getNode(row.name)
    if (node.checked) {
      //如果当前是选中checkbox,则递归设置父节点和父父节点++选中
      setParentNode(node)
      //如果当前是选中checkbox,则有子集，默认全选中
      setChildenNode(node, true)
    } else {
      //当前是取消选中,将所有子节点都取消选中
      setChildenNode(node, false)
    }
  }
  const setParentNode = (node: any) => {
    if (node.parent) {
      for (const key in node) {
        if (key === 'parent') {
          node[key].checked = true
          setParentNode(node[key])
        }
      }
    }
  }
  const setChildenNode = (node: any, checked = false) => {
    let len = node.childNodes.length
    for (let i = 0; i < len; i++) {
      node.childNodes[i].checked = checked
      setChildenNode(node.childNodes[i])
    }
  }

  //配置选项
  const treeProps = ref({
    disabled: (data: any) => {
      return data.meta.title == '首页'
    },
    label: (data: any) => {
      return data.name
    },
  })

  const selectTreeAll = ref(true) //路由页面 一键全选
  const selectAuthAll = ref(true) //页面按钮 一键全部/只读

  /***
   * @method
   */

  // 更新数据【用于编辑权限】
  const updateTree = async ({ type, menu }: any) => {
    /* 创建 默认全部权限 */
    if (type == 'create') {
      defaultChecked.value = initAllRouter.value
      return
    }

    /* 编辑 */
    const array = menu.split(',')
    const menuArray = array.map((item: any) => {
      return {
        name: StrSplit(item, '.', 0),
        authName: item,
      }
    })

    // 拿取本地路由 与 选中客户权限 比对 生成新路由页面
    const _routerList = _.cloneDeep(routerList.value)
    // 递归路由
    const diffRouter = (router: any[]) => {
      for (let i = 0; i < router.length; i++) {
        const item = router[i]

        for (let k = 0; k < menuArray.length; k++) {
          const ktem = menuArray[k]
          if (item.name == ktem.name) {
            item.authName = ktem.authName
          }
        }

        // 子集遍历
        if (item.children && item.children.length) {
          diffRouter(item.children)
        }
      }
    }

    await diffRouter(_routerList)

    dataSource.value = await _routerList
    // 选中菜单条目
    defaultChecked.value = ArrayOneValue(menuArray, 'name')
  }

  // 返回 路由名称
  const retrunRouterTitle = (name: string) => {
    const list = ArrayFlat(routerList.value, 'children')
    const row = list.filter((item: any) => item.name == name)
    return row[0].meta.title
  }
  // 返回 路由关键字
  const retrunRouterName = (node: any) => {
    return node.data.name
  }

  // 一键菜单权限
  const changeTreeSelect = (v: any) => {
    if (v) {
      treeRef.value.setCheckedKeys(initAllRouter.value)
      return
    }
    // 首页默认
    treeRef.value.setCheckedKeys(['Root', 'Index'])
  }

  // 一键页面权限
  const changeAuthSelect = async (v: any) => {
    const _routerList = _.cloneDeep(routerList.value)

    // 路由递归遍历
    const routerDiff = (array: [], v: boolean) => {
      for (let i = 0; i < array.length; i++) {
        const row: any = array[i]
        row.authName = v ? `${row.name}.all` : `${row.name}.readonly`

        if (row.children && row.children.length) {
          routerDiff(row.children, v)
        }
      }
    }
    await routerDiff(_routerList, v)
    dataSource.value = await _routerList

    // 一键菜单全选
    setTimeout(() => {
      selectTreeAll.value = true
      changeTreeSelect(true)
    }, 200)
  }

  const append = (data: VabRouteMeta) => {}
  const remove = (node: Node, data: VabRouteMeta) => {}

  /**
   * @实例
   */

  defineExpose({
    dataSource,
    treeRef,
    selectRouerList: () => {
      return treeRef.value!.getCheckedNodes(false, false)
    },
    updateTree,
  })
</script>

<style>
  .custom-tree-node {
    flex: 1;
    display: flex;
    align-items: center;
    justify-content: space-between;
    font-size: 14px;
    padding-right: 8px;
  }
  .flex {
    margin-bottom: 8px;
    .switch {
      margin-right: 6px;
    }
  }

  .vab-icon {
    color: #fbb28a;
    margin-left: 4px;
  }
</style>
